package com.cloud.lawcase.api.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.cloud.lawcase.api.bean.DictBean;
import com.cloud.lawcase.api.entity.TcDicDef;
import com.cloud.lawcase.api.entity.TcDicLawEffectLevel;
import com.cloud.lawcase.api.entity.TcDicLawExcuteType;
import com.cloud.lawcase.api.entity.TcDicLawGroup;
import com.cloud.lawcase.api.entity.TcDicLawPublishDept;
import com.cloud.lawcase.api.entity.TcDicLawRegion;
import com.cloud.lawcase.api.entity.TcDicLawSx;
import com.cloud.lawcase.api.entity.TcDicLawType;
import com.cloud.lawcase.api.entity.TcDicUnitFunc;
import com.cloud.lawcase.api.entity.TcDicUnitFuncLevel;
import com.cloud.lawcase.api.mapper.TcDicDefMapper;
import com.cloud.lawcase.api.mapper.TcDicLawEffectLevelMapper;
import com.cloud.lawcase.api.mapper.TcDicLawExcuteTypeMapper;
import com.cloud.lawcase.api.mapper.TcDicLawGroupMapper;
import com.cloud.lawcase.api.mapper.TcDicLawPublishDeptMapper;
import com.cloud.lawcase.api.mapper.TcDicLawRegionMapper;
import com.cloud.lawcase.api.mapper.TcDicLawSxMapper;
import com.cloud.lawcase.api.mapper.TcDicLawTypeMapper;
import com.cloud.lawcase.api.mapper.TcDicUnitFuncLevelMapper;
import com.cloud.lawcase.api.mapper.TcDicUnitFuncMapper;
import com.cloud.lawcase.api.service.LawDictService;
import com.cloud.lawcase.common.result.QkIcon;
import com.cloud.lawcase.common.result.QkTreeNode;
import com.cloud.lawcase.common.utils.TreeHelper;

import tk.mybatis.mapper.entity.Example;
import tk.mybatis.mapper.entity.Example.Criteria;

@Service
@Transactional
@CacheConfig(cacheNames="lawcase/cache")
public class LawDictServiceImpl implements LawDictService {

	@Autowired
	private TcDicDefMapper tcDicDefMapper;
	@Autowired
	private TcDicLawSxMapper tcDicLawSxMapper;
	@Autowired
	private TcDicLawGroupMapper tcDicLawGroupMapper;
	@Autowired
	private TcDicLawTypeMapper tcDicLawLawTypeMapper;
	@Autowired
	private TcDicLawEffectLevelMapper tcDicLawEffectLevelMapper;
	@Autowired
	private TcDicLawPublishDeptMapper tcDicLawPublishDeptMapper;
	@Autowired
	private TcDicLawRegionMapper tcDicLawRegionMapper;
	@Autowired
	private TcDicLawExcuteTypeMapper tcDicLawExcuteTypeMapper;
	@Autowired
	private TcDicUnitFuncMapper tcDicUnitFuncMapper;
	@Autowired
	private TcDicUnitFuncLevelMapper tcDicUnitFuncLevelMapper;
	@Autowired
	private JdbcTemplate jdbcTemplate;

	@Override
	public List<TcDicDef> listDictDef() {
		return tcDicDefMapper.selectAll();
	}

	@Override
	public QkTreeNode[] listDictTree(TcDicDef def) {
		List<QkTreeNode> nodes = new ArrayList<QkTreeNode>();
		String rootNodeId = def.getDicId() + def.getDicTableName();
		QkTreeNode rootNode = new QkTreeNode(rootNodeId, def.getDicName());
		rootNode.setRootFlag(true);
		rootNode.setSelectable(true);
		rootNode.setExpanded(true);
		rootNode.setIcon(QkIcon.FA_BOOK);
		nodes.add(rootNode);
		StringBuilder sqlBuilder = new StringBuilder("select ").append(def.getDicPkCol()).append(" as id, ")
				.append(def.getDicLabelCol()).append(" as label");
		if (!StringUtils.isEmpty(def.getDicSeniorCol())) {
			sqlBuilder.append(", ").append(def.getDicSeniorCol()).append("  as seniorId");
		}
		if(!StringUtils.isEmpty(def.getDicCodeCol())){
			sqlBuilder.append(", ").append(def.getDicCodeCol()).append(" as type");
		}
		sqlBuilder.append(" from ").append(def.getDicTableName());
		if (!StringUtils.isEmpty(def.getDicOrderCol())) {
			sqlBuilder.append(" order by ").append(def.getDicOrderCol());
		}
		List<QkTreeNode> dictNodes = jdbcTemplate.query(sqlBuilder.toString(),
				new BeanPropertyRowMapper<>(QkTreeNode.class));
		for (QkTreeNode n : dictNodes) {
			n.setSelectable(true);
			n.setIcon(QkIcon.FA_BOOKMARK);
			if (StringUtils.isEmpty(n.getSeniorId()) || "0".equals(n.getSeniorId())) {
				n.setSeniorId(rootNodeId);
			}
			if(!StringUtils.isEmpty(n.getType())){
				n.getData().put("code", n.getType());
			}
		}
		nodes.addAll(dictNodes);
		return TreeHelper.buildList2Tree(nodes);
	}

	@Override
	public DictBean saveUpdateDict(DictBean bean) {
		TcDicDef def = tcDicDefMapper.selectByPrimaryKey(bean.getDicId());
		if (StringUtils.isEmpty(bean.getPkValue())) {
			// 新增
			Integer id = jdbcTemplate.queryForObject(
					"select max(" + def.getDicPkCol() + ") from " + def.getDicTableName(), Integer.class);

			StringBuilder sqlBuilder = new StringBuilder("insert into ").append(def.getDicTableName()).append("(");
			StringBuilder paramsBuilder = new StringBuilder("values (?");
			List<Object> params = new ArrayList<Object>();
			Integer pkValue = id + 1;
			params.add(pkValue);
			if(!def.getDicPkCol().equals(def.getDicKeyCol())){
				sqlBuilder.append(def.getDicPkCol()).append(", ");
				paramsBuilder.append(", ?");
				params.add(bean.getKeyValue());
			}
			sqlBuilder.append(def.getDicKeyCol()).append(", ").append(def.getDicLabelCol());
			paramsBuilder.append(", ?");
			params.add(bean.getLabelValue());
			
			if (!StringUtils.isEmpty(def.getDicOrderCol())) { // 排序
				sqlBuilder.append(", ").append(def.getDicOrderCol());
				paramsBuilder.append(", ?");
				if(!StringUtils.isEmpty(bean.getOrderValue()+"")){
					params.add(bean.getOrderValue());
				}else{
					params.add(pkValue);
				}
				
			}
			if (!StringUtils.isEmpty(def.getDicSeniorCol())) { // 上级
				sqlBuilder.append(", ").append(def.getDicSeniorCol());
				paramsBuilder.append(", ?");
				params.add(bean.getSeniorValue());
				if (!StringUtils.isEmpty(def.getDicCodeCol())) { // 编码
					sqlBuilder.append(", ").append(def.getDicCodeCol());
					paramsBuilder.append(", ?");
					List<String> seniorCode = jdbcTemplate.queryForList("select " + def.getDicCodeCol() + " from "
							+ def.getDicTableName() + " where " + def.getDicKeyCol() + " = ?", String.class,
							bean.getSeniorValue());
					if(null == seniorCode || seniorCode.size() == 0){
						params.add("/"+pkValue+"/");
					}else{
						params.add(seniorCode.get(0) + pkValue + "/");
					}
					
				}
			}
			if (!StringUtils.isEmpty(def.getDicEnableCol())) { // 启用标记
				sqlBuilder.append(", ").append(def.getDicEnableCol());
				paramsBuilder.append(", ?");
				params.add(bean.getEnableValue());
			}
			sqlBuilder.append(") ").append(paramsBuilder).append(")");
			jdbcTemplate.update(sqlBuilder.toString(), params.toArray(new Object[params.size()]));

		} else {
			// 修改
			StringBuilder sqlBuilder = new StringBuilder("update ").append(def.getDicTableName());
			List<Object> params = new ArrayList<Object>();
			sqlBuilder.append(" set ").append(def.getDicLabelCol()).append(" = ?");
			params.add(bean.getLabelValue());
			
			if(!def.getDicPkCol().equals(def.getDicKeyCol())){
				sqlBuilder.append(", ").append(def.getDicKeyCol()).append(" = ? ");
				params.add(bean.getKeyValue());
			}
			if (!StringUtils.isEmpty(def.getDicOrderCol())) { // 排序
				sqlBuilder.append(", ").append(def.getDicOrderCol()).append(" = ? ");
				params.add(bean.getOrderValue());
			}
			if (!StringUtils.isEmpty(def.getDicSeniorCol())) { // 上级
				sqlBuilder.append(", ").append(def.getDicSeniorCol()).append(" = ? ");
				params.add(bean.getSeniorValue());
				if (!StringUtils.isEmpty(def.getDicCodeCol())) { // 编码
					sqlBuilder.append(", ").append(def.getDicCodeCol()).append(" = ? ");
					List<String> seniorCode = jdbcTemplate.queryForList("select " + def.getDicCodeCol() + " from "
							+ def.getDicTableName() + " where " + def.getDicKeyCol() + " = ?", String.class,
							bean.getSeniorValue());
					if(null == seniorCode || seniorCode.size() == 0){
						params.add("/"+bean.getPkValue()+"/");
					}else{
						params.add(seniorCode.get(0) + bean.getPkValue() + "/");
					}
				}
			}
			if (!StringUtils.isEmpty(def.getDicEnableCol())) { // 启用标记
				sqlBuilder.append(", ").append(def.getDicEnableCol()).append(" = ?");
				params.add(bean.getEnableValue());
			}
			sqlBuilder.append(" where ").append(def.getDicPkCol()).append(" = ?");
			params.add(bean.getPkValue());
			jdbcTemplate.update(sqlBuilder.toString(), params.toArray(new Object[params.size()]));
		}
		return bean;
	}

	@Override
	public void deleteDict(DictBean bean) {
		TcDicDef def = tcDicDefMapper.selectByPrimaryKey(bean.getDicId());
		if (StringUtils.isEmpty(bean.getSeniorValue())) {
			// 不分层级
			jdbcTemplate.update("delete from " + def.getDicTableName() + " where " + def.getDicPkCol() + " = ?",
					bean.getPkValue());
		} else {
			// 移除当前节点以及所有下级节点
			jdbcTemplate.update("delete from " + def.getDicTableName() + " where " + def.getDicCodeCol() + " like '"
					+ bean.getCodeValue() + "%'");
		}
	}

	@Override
	public DictBean loadDictDetail(int dicDefId, int id) {
		TcDicDef def = tcDicDefMapper.selectByPrimaryKey(dicDefId);
		StringBuilder sb = new StringBuilder("select ").append(def.getDicPkCol()).append(" as pkValue, ")
				.append(def.getDicKeyCol()).append(" as keyValue, ").append(def.getDicLabelCol())
				.append(" as labelValue");
		if (!StringUtils.isEmpty(def.getDicSeniorCol())) { // 上级编号
			sb.append(", ").append(def.getDicSeniorCol()).append(" as seniorValue");
		}
		if (!StringUtils.isEmpty(def.getDicOrderCol())) { // 排序
			sb.append(", ").append(def.getDicOrderCol()).append(" as orderValue");
		}
		if (!StringUtils.isEmpty(def.getDicEnableCol())) { // 启用
			sb.append(", ").append(def.getDicEnableCol()).append(" as enableValue");
		}
		if (!StringUtils.isEmpty(def.getDicCodeCol())) { // 层次型编码
			sb.append(", ").append(def.getDicCodeCol()).append(" as codeValue");
		}
		sb.append(" from ").append(def.getDicTableName()).append(" where ").append(def.getDicPkCol()).append(" = ?");
		List<Map<String, Object>> bean = jdbcTemplate.queryForList(sb.toString(), id);
		if (null != bean && bean.size() == 1) {
			Map<String, Object> map = bean.get(0);
			DictBean result = JSON.parseObject(JSON.toJSONString(map), DictBean.class);
			return result;
		}
		return null;
	}
	
	@Override
	@Cacheable
	public List<TcDicLawSx> listSxItems() {
		Example example = new Example(TcDicLawSx.class);
		Criteria criteria = example.createCriteria();
		criteria.andEqualTo("enableFlag", 1);
		example.orderBy("displayOrder");
		return tcDicLawSxMapper.selectByExample(example);
	}

	@Override
	@Cacheable
	public List<TcDicLawType> listLawTypeItems() {
		Example example = new Example(TcDicLawType.class);
		Criteria criteria = example.createCriteria();
		criteria.andEqualTo("enableFlag", 1);
		example.orderBy("displayOrder");
		return tcDicLawLawTypeMapper.selectByExample(example);
	}

	@Override
	@Cacheable
	public List<TcDicLawRegion> listLawRegionItems() {
		Example example = new Example(TcDicLawRegion.class);
		Criteria criteria = example.createCriteria();
		criteria.andEqualTo("enableFlag", 1);
		example.orderBy("displayOrder");
		return tcDicLawRegionMapper.selectByExample(example);
	}

	@Override
	@Cacheable
	public List<TcDicLawEffectLevel> listLawEffectLevelItems() {
		Example example = new Example(TcDicLawEffectLevel.class);
		Criteria criteria = example.createCriteria();
		criteria.andEqualTo("enableFlag", 1);
		example.orderBy("displayOrder");
		return tcDicLawEffectLevelMapper.selectByExample(example);
	}

	@Override
	@Cacheable
	public List<TcDicLawPublishDept> listLawPublishDeptItems() {
		Example example = new Example(TcDicLawPublishDept.class);
		Criteria criteria = example.createCriteria();
		criteria.andEqualTo("enableFlag", 1);
		example.orderBy("displayOrder");
		return tcDicLawPublishDeptMapper.selectByExample(example);
	}

	@Override
	@Cacheable
	public List<TcDicLawExcuteType> listLawExcuteTypes() {
		Example example = new Example(TcDicLawExcuteType.class);
		Criteria criteria = example.createCriteria();
		criteria.andEqualTo("enableFlag", 1);
		example.orderBy("displayOrder");
		return tcDicLawExcuteTypeMapper.selectByExample(example);
	}

	@Override
	@Cacheable
	public List<TcDicLawGroup> listAllGroups() {
		Example example = new Example(TcDicLawGroup.class);
		Criteria criteria = example.createCriteria();
		criteria.andEqualTo("isValid", 1);
		example.orderBy("displayOrder");
		return tcDicLawGroupMapper.selectByExample(example);
		
		
	}

	@Override
	@Cacheable
	public List<TcDicUnitFunc> listFuncUnits() {
		Example example = new Example(TcDicUnitFunc.class);
		Criteria criteria = example.createCriteria();
		criteria.andEqualTo("enableFlag", 1);
		example.orderBy("displayOrder");
		return tcDicUnitFuncMapper.selectByExample(example);
	}

	@Override
	@Cacheable
	public List<TcDicUnitFuncLevel> listFuncUnitLevels() {
		Example example = new Example(TcDicUnitFuncLevel.class);
		Criteria criteria = example.createCriteria();
		criteria.andEqualTo("enableFlag", 1);
		example.orderBy("displayOrder");
		return tcDicUnitFuncLevelMapper.selectByExample(example);
	}

	@Override
	@Cacheable
	public QkTreeNode[] listGroupTree() {
		List<TcDicLawGroup> groups = listAllGroups();
		List<QkTreeNode> nodes = new ArrayList<QkTreeNode>(groups.size());
		for (TcDicLawGroup group : groups) {
			QkTreeNode node = new QkTreeNode(group.getGroupId(), group.getGroupName());
			node.setCollapsedIcon(QkIcon.FA_FOLDER);
			node.setExpandedIcon(QkIcon.FA_FOLDER_OPEN);
			node.setSeniorId(group.getSeniorGroupId() + "");
			node.setSelectable(true);
			node.getData().put("code", group.getGroupCode());
			if (group.getSeniorGroupId() <= 0) {
				node.setRootFlag(true);
			}
			nodes.add(node);
		}
		return TreeHelper.buildList2Tree(nodes);
	}
	
	
	@Override
	@Caching(evict = {
			@CacheEvict(key="'com.cloud.lawcase.api.service.impl.LawDictServiceImpl_listAllGroups'"),
			@CacheEvict(key="'com.cloud.lawcase.api.service.impl.LawDictServiceImpl_listGroupTree'"),
			@CacheEvict(key="'com.cloud.lawcase.api.service.impl.LawDictServiceImpl_listLawEffectLevelItems'"),
			@CacheEvict(key="'com.cloud.lawcase.api.service.impl.LawDictServiceImpl_listLawPublishDeptItems'"),
			@CacheEvict(key="'com.cloud.lawcase.api.service.impl.LawDictServiceImpl_listLawRegionItems'"),
			@CacheEvict(key="'com.cloud.lawcase.api.service.impl.LawDictServiceImpl_listLawTypeItems'"),
			@CacheEvict(key="'com.cloud.lawcase.api.service.impl.LawDictServiceImpl_listSxItems'"),
			@CacheEvict(key="'com.cloud.lawcase.api.service.impl.LawDictServiceImpl_listLawExcuteTypes'"),
			@CacheEvict(key="'com.cloud.lawcase.api.service.impl.LawDictServiceImpl_listFuncUnits'"),
			@CacheEvict(key="'com.cloud.lawcase.api.service.impl.LawDictServiceImpl_listFuncUnitLevels'")
		})
	public void refreshCache() {
		//do nothing, just evict cache...
	}


}
